package com.zl.tby.websocket;

import com.zl.tby.service.ITbySmartBoxHistoryService;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Init;
import org.noear.solon.annotation.Inject;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;

/**
 * 智能箱websocket
 * @author changpeng
 * @since 2025/10/14 15:43
 */
@Slf4j
@Component
public class WsClientWithPingPong {
    /**客户端*/
    private WebSocketClient webSocketClient;;
    @Inject("${smart-box.ws-url}")
    private String serverUrl;
    @Inject("${smart-box.api-key}")
    private String serverApiKey;

    @Inject
    private ITbySmartBoxHistoryService tbySmartBoxHistoryService;

    @Init
    public void init() {
        System.out.println("开启websocket监听");
        start();
    }

    // 心跳定时器
    private Timer pingTimer;
    // 连接状态
    private boolean isConnected = false;

    // 配置参数
    private static final int PING_INTERVAL = 30;
    private static final int RECONNECT_DELAY = 5;
    private static final int CONNECT_TIMEOUT = 5000;

    /**
     * 初始化并连接到 WebSocket 服务端
     */
    public void start() {
        try {
            URI serverUri = new URI(serverUrl + "?apikey=" + serverApiKey);

            // 创建 WebSocket 客户端实例
            webSocketClient = new WebSocketClient(serverUri) {
                // 连接成功回调
                @Override
                public void onOpen(ServerHandshake handshakedata) {
                    isConnected = true;
                    log.info("WebSocket 连接成功！服务端地址：{}", serverUrl);
                    log.info("服务端握手信息：{}", handshakedata.getHttpStatusMessage());

                    // 启动 Ping 心跳
                    startPingTimer();
                }

                // 收到消息回调（核心：监听数据）
                @Override
                public void onMessage(String message) {
                    log.error("收到文本消息：{}", message);
                    tbySmartBoxHistoryService.add(message);
                }

                // 连接关闭回调
                @Override
                public void onClose(int code, String reason, boolean remote) {
                    isConnected = false;
                    log.warn("WebSocket 连接关闭！状态码：{}，原因：{}，是否远程关闭：{}", code, reason, remote);
                    // 停止心跳
                    stopPingTimer();
                    // 触发重连
                    reconnect();
                }

                // 连接错误回调
                @Override
                public void onError(Exception ex) {
                    log.error("WebSocket 连接错误！", ex);
                    isConnected = false;
                    // 停止心跳
                    stopPingTimer();
                    // 触发重连
                    reconnect();
                }
            };

            // 发起连接
            webSocketClient.connect();

        } catch (URISyntaxException e) {
            log.error("WebSocket 地址格式错误：{}", serverUrl, e);
        } catch (Exception e) {
            log.error("WebSocket 连接失败！", e);
            reconnect();
        }
    }


    /**
     * 启动 Ping 心跳定时器（定时发送 Ping 帧）
     */
    private void startPingTimer() {
        // 先停止已有定时器
        stopPingTimer();

        pingTimer = new Timer("Ws-Ping-Timer", true);
        pingTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                try {
                    if (isConnected && webSocketClient != null && webSocketClient.isOpen()) {
                        // 发送 Ping 帧（java-websocket-ns 会自动处理 Ping 帧格式）
                        webSocketClient.sendPing();
                        log.debug("已发送 Ping 心跳");
                    } else {
                        log.warn("连接已关闭，停止发送 Ping");
                        stopPingTimer();
                    }
                } catch (Exception e) {
                    log.error("发送 Ping 心跳失败！", e);
                    stopPingTimer();
                }
            }
        }, 0, PING_INTERVAL * 1000); // 立即启动，每 PING_INTERVAL 秒发送一次
    }


    /**
     * 停止 Ping 心跳定时器
     */
    private void stopPingTimer() {
        if (pingTimer != null) {
            pingTimer.cancel();
            pingTimer = null;
            log.debug("Ping 心跳定时器已停止");
        }
    }


    /**
     * 断线重连
     */
    private void reconnect() {
        if (webSocketClient != null && webSocketClient.isClosing() || webSocketClient.isClosed()) {
            log.info("{} 秒后尝试重连...", RECONNECT_DELAY);

            new Thread(() -> {
                try {
                    TimeUnit.SECONDS.sleep(RECONNECT_DELAY);
                    // 关闭旧连接
                    if (webSocketClient != null) {
                        webSocketClient.close();
                    }
                    // 重新连接
                    start();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.error("重连线程被中断", e);
                }
            }).start();
        }
    }


    /**
     * 发送文本消息到服务端
     */
    public void sendMessage(String message) {
        if (!isConnected || webSocketClient == null || !webSocketClient.isOpen()) {
            log.error("发送失败：WebSocket 未连接");
            return;
        }

        try {
            webSocketClient.send(message);
            log.info("已发送消息：{}", message);
        } catch (Exception e) {
            log.error("发送消息失败！", e);
        }
    }

    /**
     * 关闭连接（释放资源）
     */
    public void close() {
        stopPingTimer();

        if (webSocketClient != null && webSocketClient.isOpen()) {
            try {
                webSocketClient.close(1000, "正常关闭"); // 1000 表示正常关闭
                log.info("WebSocket 客户端已手动关闭");
            } catch (Exception e) {
                log.error("关闭 WebSocket 连接失败！", e);
            }
        }
    }

    // 获取连接状态
    public boolean isConnected() {
        return isConnected;
    }
}
